<%@ page language="java" contentType="text/html; charset=UTF-8"
	pageEncoding="UTF-8"%>

<%
	String path = request.getContextPath();
	String basePath = request.getScheme() + "://"
			+ request.getServerName() + ":" + request.getServerPort()
			+ path + "/";
	String deckPath = basePath + "deck/";
%>

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=1024, user-scalable=no">
<title>Learn Struts2</title>

<link rel="stylesheet" type="text/css"
	href="<%=basePath%>syntax_highlighter/jquery.snippet.css" />

<!-- Required stylesheet -->
<link rel="stylesheet" href="<%=deckPath%>core/deck.core.css">

<!-- Extension CSS files go here. Remove or add as needed. -->
<link rel="stylesheet" href="<%=deckPath%>extensions/goto/deck.goto.css">
<link rel="stylesheet" href="<%=deckPath%>extensions/menu/deck.menu.css">
<link rel="stylesheet"
	href="<%=deckPath%>extensions/navigation/deck.navigation.css">
<link rel="stylesheet"
	href="<%=deckPath%>extensions/status/deck.status.css">
<link rel="stylesheet" href="<%=deckPath%>extensions/hash/deck.hash.css">
<link rel="stylesheet"
	href="<%=deckPath%>extensions/scale/deck.scale.css">

<!-- Style theme. More available in /themes/style/ or create your own. -->
<link rel="stylesheet" href="<%=deckPath%>themes/style/web-2.0.css">

<!-- Transition theme. More available in /themes/transition/ or create your own. -->
<link rel="stylesheet"
	href="<%=deckPath%>themes/transition/horizontal-slide.css">

<!-- Required Modernizr file -->
<script src="<%=deckPath%>modernizr.custom.js"></script>
</head>
<body class="deck-container">

	<!-- Begin slides. Just make elements with a class of slide. -->

	<section class="slide">
	<h2>Basic Usage of this MVC framework</h2>
	<p>
		<a href="path/path.action">path</a>
	</p>
	<p>
		<a href="user/userAdd.action">ActionMethod</a>
	</p>
	<p>
		<a href="user/user!add">DMI</a>
	</p>
	</section>

	<section class="slide">
	<h2>Wildcard</h2>
	<p>It reduces the amount of effort in configuration.<br>
	<b>But one must abide by the principle of "Convention over
		Configuration".</b> (or coding by Convention)</p>
	<a href="actions/studentadd">actions/studentadd</a> <br>
	<a href="actions/studentdelete">actions/studentdelete</a> <br>
	<p><br>An example of neat configuration</p>
	<pre class="wildcard_example">
	&lt;action name="*_*" class="myaction.{1}Action"&gt;
    	&lt;result&gt;/wildcard/{1}_{2}_success.jsp&lt;/result&gt;
    &lt;/action&gt;</pre> <br>

	<a href="actions/Teacher_add">actions/Teacher_add</a> <br>
	<a href="actions/Teacher_delete">actions/Teacher_delete</a> <br>
	<ul>
		<li>If there are more than 1 action that fits the request,
			priority is given to the one with the most accurate name<br>
		<li>If there are more than 1 action that fits the request and
			whose name contains wildcard chars, priority is given to the one that
			appears the first
	</ul>
	</section>

	<section class="slide">
	<h3>Parameters</h3>
	<ul>
		<li>write getters and setters for the variables in the action class and just pass in the parameters as part of the URL<br>
		<li>Struts2 invokes the setter method, instead of writing into the variable directly.<br>
		<li>use the following format in the URL: <b>actionName!method?param1=xxx&amp;param2=xxx</b><br>
	</ul>
	<a href="user/user!add?name=a&age=100">add this user</a>
	<p>
	<h3>Use Domain Model</h3>
	<ul>
		<li>Creates a new class with getters and setters for various parameters<br>
		<li>Simply have an instance of this class in the action class
			with its getter and setter, in order to pass in the variables<br>
		<li>Use the following format in the URL:
		<b>actionName!method?modelClass.attr1=xxx&amp;modelClass.attr2=xxx</b><br>
	</ul>
	<a href="user/user!addModel?user.name=joker&user.age=1">add this user</a><br>
	
	<p><b>Data Transfer Objects</b> are used when the number of parameters and number of variables 
	in the new class do not match exactly.<br>
	<ul>
		<li>Have a DTO that contains all fields that correspond to the parameters.
		<li>use these data to generate the desired entity class. 
			(by having a method createDomainModel(DTO))
	</ul></p>

	<h3>Model Driven Param Input</h3>
	<p>The URL format is the same as the first method for param input. But the action class also 
	uses the wrapper class as does the second one. This is done by implementing the interface
	ModelDriven&lt;T&gt;.</p>
	<a href="user/user!add?name=apple&age=101">add this user</a><br>
	</section>
	
	<section class="slide">
	<h3>Character Encoding and Simple Data Validation</h3>
	<p>Have this line in struts.xml:</p>
	<pre class="xml">
	&lt;constant name="struts.i18n.encoding" value="GBK" /&gt;</pre>
	<p>The constants of struts.xml in Struts2 are in <br>
	struts2-core-*.jar, org.apache.struts2/static/default.properties</p>
	<form action="user/user!addVerify" method="post">
		姓名：<input type="text" name="name">
		<input type="submit" name="submit">
	</form>
	<p>For error information, refer to how <a href="<%=basePath%>user_add_fail.jsp">user_add_fail.jsp</a>
	is written</p>
	</section>
	
	<section class="slide">
	<h3>Retrieve Web Elements</h3>
	<p>mainly Request, Session and Application<br>
	</p>
	<form name="how_to_get_web_elements" action="" method="post">
	 	username: <input type="text" name="name">
	 	password: <input type="text" name="password"><br>
	 	<input type="submit" value="submit1" onclick=
		 	"javascript:document.how_to_get_web_elements.action='login/login1';document.how_to_get_web_elements.submit();" />
	 	<input type="submit" value="submit2" onclick=
	 		"javascript:document.how_to_get_web_elements.action='login/login2';document.how_to_get_web_elements.submit();" />
	 	<input type="submit" value="submit3" onclick=
			"javascript:document.how_to_get_web_elements.action='login/login3';document.how_to_get_web_elements.submit();" />
	 	<input type="submit" value="submit4" onclick=
	 		"javascript:document.how_to_get_web_elements.action='login/login4';document.how_to_get_web_elements.submit();" />
	</form>
	<ul>
		<li>put all information into the map obtained from ActionContext<br>
		<pre class="login">
	private Map&lt;String, Object&gt; myRequest;
	private Map&lt;String, Object&gt; mySession;
	private Map&lt;String, Object&gt; myApplication;

	@SuppressWarnings("unchecked")
	public LoginAction1() {
		myRequest = (Map&lt;String, Object&gt;) ActionContext.getContext().get(
				"request");
		mySession = ActionContext.getContext().getSession();
		myApplication = ActionContext.getContext().getApplication();
	}

	public String execute() {
		myRequest.put("r1", "r1");
		mySession.put("s1", "s1");
		myApplication.put("a1", "a1");
		return SUCCESS;
	}
		</pre>
		<li>Use IoC pattern by implementing RequestAware, SessionAware and ApplicationAware interfaces.<br>
			<b>This is the recommended one.</b><br>
		<pre class="login">
	//not initialized, but the setters are called
	private Map<String, Object> myRequest;
	private Map<String, Object> mySession;
	private Map<String, Object> myApplication;
	
	public String execute() {
		myRequest.put("r1", "r2");
		mySession.put("s1", "s2");
		myApplication.put("a1", "a2");
		return SUCCESS;
	}
		</pre>
		<li>get HttpServletRequest, HttpSession and HttpServletContext directly<br>
		<pre class="login">
	private HttpServletRequest myRequest;
	private HttpSession mySession;
	private ServletContext myApplication;

	public LoginAction3() {
		myRequest = ServletActionContext.getRequest();
		mySession = myRequest.getSession();
		myApplication = mySession.getServletContext();
	}

	public String execute() { 
		myRequest.setAttribute("r1", "r3");
		mySession.setAttribute("s1", "s3");
		myApplication.setAttribute("a1", "a3");
		return SUCCESS;
	}
		</pre>
		<li>IoC: implement ServletRequestAware interface<br>
		<pre class="login">
	private HttpServletRequest myRequest;
	private HttpSession mySession;
	private ServletContext myApplication;
	
	public String execute() { 
		myRequest.setAttribute("r1", "r4");
		mySession.setAttribute("s1", "s4");
		myApplication.setAttribute("a1", "a4");
		return SUCCESS;
	}
	
	@Override
	public void setServletRequest(HttpServletRequest servletRequest) {
		myRequest = servletRequest;
		mySession = myRequest.getSession();
		myApplication = mySession.getServletContext();
	}
		</pre>
	</ul><br>
	</section>
	
	<section class="slide">
	<h3>Tips about Action</h3>
	<p>Tip1: use &lt;include file="login.xml"/&gt; to include other xml files which contain packages. <br>
	see login.xml in src folder
	</p>
	<p>Tip2: use &lt;default-action-ref name="index"&gt;&lt;/default-action-ref&gt; for default action<br>
	If a page is not found, this default action will be invoked.
	</p>
	</section>
	
	<section class="slide">
	<h3>Result type</h3>
	<ul>
		<li>dispatcher (default)
		<li>redirect: the jsp path is used instead of action
		<li>chain (forward to another action, but the URL still shows this action)<br>
			Use param tag for actions in different packages
		<li>redirectAction: similar to redirect
		<li>freemarker
		<li>httpheader (head info)
		<li>stream (download)
		<li>velocity
		<li>xslt
		<li>plaintext (source code)
		<li>tiles
	</ul>
	<h3>global result</h3>
	<pre class="xml">
	&lt;global-results&gt;
        &lt;result name="global_result_name"&gt;/Error.jsp&lt;/result&gt;
    &lt;/global-results&gt;
	</pre>
	<p>
	If the execute() in Action return this global_result_name, it will jump to this default page.<br>
	Modify extends property in package to use the global results in other packages<br>
	</p>
	</section>
	
	<section class="slide">
	<h3>Dynamic Result</h3>
	<form action="user/dynamicUser!dynamicAdd" method="post">
		name: <input type="text" name="name">
		<input type="submit" value="correct name is anything that's not empty">
	</form>
	<p>
	$&#123;&#125; sign denotes retrieving from value stack<br>
	this is written into the value between result tags in the XML.</p>
	<h3>result with parameters</h3>
	<p>
	If a server request is forwarded to other actions, all of them share the same value stack.<br>
	For client redirecting, the parameters should be passed in again.<br>
	Also, the parameter should be retrieved from the action context instead of the value stack, because
		the page is redirected to a jsp address, instead of an action. (see the following link)
	</p>
	<a href="user/param?name=joker">param in client redirecting</a><br>
	</section>
	
	<section class="slide">
	<h3>OGNL Expression</h3>
	<a href="ognl/Ognl_addModel?user.name=joker&user.password=hahaha&cat.friend.name=doggg">ognl page</a><br>
	</section>

	<!-- End slides. -->


	<!-- Begin extension snippets. Add or remove as needed. -->

	<!-- deck.navigation snippet -->
	<a href="#" class="deck-prev-link" title="Previous">&#8592;</a>
	<a href="#" class="deck-next-link" title="Next">&#8594;</a>

	<!-- deck.status snippet -->
	<p class="deck-status">
		<span class="deck-status-current"></span> / <span
			class="deck-status-total"></span>
	</p>

	<!-- deck.goto snippet -->
	<form action="." method="get" class="goto-form">
		<label for="goto-slide">Go to slide:</label> <input type="text"
			name="slidenum" id="goto-slide" list="goto-datalist">
		<datalist id="goto-datalist"></datalist>
		<input type="submit" value="Go">
	</form>

	<!-- deck.hash snippet -->
	<a href="." title="Permalink to this slide" class="deck-permalink">#</a>

	<!-- End extension snippets. -->


	<!-- Required JS files. -->
	<script type="text/javascript"
		src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js"></script>
	<script src="<%=deckPath%>core/deck.core.js"></script>

	<!-- Extension JS files. Add or remove as needed. -->
	<script src="<%=deckPath%>core/deck.core.js"></script>
	<script src="<%=deckPath%>extensions/hash/deck.hash.js"></script>
	<script src="<%=deckPath%>extensions/menu/deck.menu.js"></script>
	<script src="<%=deckPath%>extensions/goto/deck.goto.js"></script>
	<script src="<%=deckPath%>extensions/status/deck.status.js"></script>
	<script src="<%=deckPath%>extensions/navigation/deck.navigation.js"></script>
	<script src="<%=deckPath%>extensions/scale/deck.scale.js"></script>

	<script>
		$(function() {
			$.deck('.slide');
		});
	</script>

	<script type="text/javascript"
		src="<%=basePath%>syntax_highlighter/jquery.snippet.js"></script>

	<script type="text/javascript">
		$(document).ready(function() {
			$("pre.wildcard_example").snippet("xml", {
				style : "blacknblue"
			});
		});
		$(document).ready(function() {
			$("pre.xml").snippet("xml", {
				style : "blacknblue"
			});
		});
		$(document).ready(function() {
			$("pre.login").snippet("java", {
				style: "blacknblue", collapse: true,
				showMsg: "code for writing into web elements",
				hideMsg: "collapse code"
			});
		});
	</script>
</body>
</html>